package org.snia.server.ejb.entitydata;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;

import javax.ejb.Local;
import javax.ejb.Remote;
import javax.ejb.Stateless;

import org.apache.commons.vfs.FileObject;
import org.apache.commons.vfs.FileSystemException;
import org.apache.commons.vfs.FileSystemManager;
import org.apache.commons.vfs.RandomAccessContent;
import org.apache.commons.vfs.VFS;
import org.apache.commons.vfs.util.RandomAccessMode;
import org.snia.cdmi.Constants;
import org.snia.cdmi.ErrorCodes;
import org.snia.cdmi.exception.InternalException;
import org.snia.util.JuuidUtils;

@Stateless
@Local(LocalEntityDataOperation.class)
@Remote(EntityDataOperation.class)
public class EntityDataBean implements LocalEntityDataOperation {

	@Override
	public void createRealData(String md5, InputStream input){
		String uuidpath = JuuidUtils.getuuidPath(md5);
		String dir = Constants.DATA_STORE_URL + File.separator + uuidpath;
		try {
			FileSystemManager mgr = VFS.getManager();
			String filepath = dir + File.separator + md5;
			FileObject file = mgr.resolveFile(filepath);
			if (!file.exists()) {
				file.createFile();
			}

			byte[] buf = new byte[192 * 1024]; // 192K buffer(刷一次磁盘)

			RandomAccessContent content = file.getContent()
					.getRandomAccessContent(RandomAccessMode.READWRITE);
			content.seek(0);

			int bytesRead = 0;
			input.reset(); // 重置指针
			while ((bytesRead = input.read(buf, 0, buf.length)) != -1) {
				content.write(buf, 0, bytesRead);
			}
			content.close();// 关闭文件流
			file.close();
		} catch (FileSystemException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			try {
				input.close();
			} catch (Exception e) {
				System.err
						.println("Unable to close input stream of hash candidate: "
								+ e);
			}
		}
		
		// //下面是老代码
		// File folder = new File(dir);
		// if (!folder.exists()) {
		// folder.mkdirs();
		// }
		//
		// String filepath = dir + File.separator + md5;
		// File file = new File(filepath);
		// try {
		// if(!file.exists()){
		// file.createNewFile();
		// }
		// byte[] buf = new byte[192 * 1024]; // 192K buffer(刷一次磁盘)
		//
		// RandomAccessFile rf = new RandomAccessFile(filepath, "rw");
		// // FileChannel chanel = new FileChannel();
		// rf.seek(0);
		// int bytesRead = 0;
		// input.reset(); //重置指针
		// while ((bytesRead = input.read(buf, 0, buf.length)) != -1) {
		// rf.write(buf, 0, bytesRead);
		// }
		// rf.close();// 关闭文件流
		// } catch (IOException e) {
		// e.printStackTrace();
		// } finally {
		// try {
		// input.close();
		// } catch (Exception e) {
		// System.err.println("Unable to close input stream of hash candidate: "
		// + e);
		// }
		// }
	}
	
	@Override
	public InputStream getRealData(String md5) {
		String uuidpath = JuuidUtils.getuuidPath(md5);
		String dir = Constants.DATA_STORE_URL + File.separator + uuidpath;
		try {
			FileSystemManager mgr = VFS.getManager();
			String filepath = dir + File.separator + md5;
			FileObject file = mgr.resolveFile(filepath);
			if(!file.exists()){
				//系统故障导致数据不存在
				throw new InternalException(ErrorCodes.InternalError);
			}
			return file.getContent().getInputStream();	
		} catch (FileSystemException e1) {
			e1.printStackTrace();
			return null;
		}
	}
	
	/**
	 * 真正的删除本地的文件片。
	 * @param md5
	 */
	@Override
	public void deleteRealData(String md5) {
		String uuidpath = JuuidUtils.getuuidPath(md5);
		String dir = Constants.DATA_STORE_URL + File.separator + uuidpath;
		try {
			FileSystemManager mgr = VFS.getManager();
			String filepath = dir + File.separator + md5;
			FileObject file = mgr.resolveFile(filepath);
			if(file.exists()){
				file.delete();
			}
			
			//TODO 需要删除父的空目录
			FileObject parent = file.getParent();
			if(parent.getChildren().length == 0) {
				parent.delete();
				//TODO 再循环往上删
			}
		} catch (FileSystemException e1) {
			e1.printStackTrace();
		}
	}
}
